package com.baseproject.util;


import android.util.Log;

import com.baseproject.BuildConfig;

public class LogUtils {

    private static final boolean allowD = BuildConfig.LOG_ENABLE;

    private static final int FLAG_D = 0;
    private static final int FLAG_E = 1;
    private static boolean allowLogCatchedException = BuildConfig.LOG_EXCEPTION_ENABLE;

    //getStackTrace()[3],取第四个的原因是前两个分别为vm和Thread的方法，下标2是当前的d()方法，调用d()的方法的下标为3。

    public static void d(String tag, String msg) {
        if (allowD) {
            Log.d(tag, msg);
        }
    }

    /**
     * 截断输出日志
     */
    public static void d(String msg) {
        logMsg(msg, FLAG_D);
    }

    /**
     * 截断输出日志
     */
    public static void e(String msg) {
        logMsg(msg, FLAG_E);
    }

    private static void logMsg(String msg, int flag) {
        if (!allowD) {
            return;
        }
        StackTraceElement caller = Thread.currentThread().getStackTrace()[4];
        String tag = generateTag(caller);
        String methodName = "[" + caller.getMethodName() + "]: ";

        int segmentSize = 3 * 1024;
        long length = msg.length();
        if (length <= segmentSize) {// 长度小于等于限制直接打印
            switch (flag) {
                case FLAG_D:
                    logd(tag, methodName, msg);
                    break;
                case FLAG_E:
                    loge(tag, methodName, msg);
                    break;
            }
        } else {
            while (msg.length() > segmentSize) {// 循环分段打印日志
                String logContent = msg.substring(0, segmentSize);
                msg = msg.substring(segmentSize, msg.length());
                switch (flag) {
                    case FLAG_D:
                        logd(tag, logContent, msg);
                        break;
                    case FLAG_E:
                        loge(tag, logContent, msg);
                        break;
                }
            }
            switch (flag) {// 打印剩余日志
                case FLAG_D:
                    logd(tag, methodName, msg);
                    break;
                case FLAG_E:
                    loge(tag, methodName, msg);
                    break;
            }
        }
    }

    public static void d(String content, Throwable thr) {
        if (!allowD) {
            return;
        }
        StackTraceElement caller = Thread.currentThread().getStackTrace()[3];
        String tag = generateTag(caller);
        String methodName = "[" + caller.getMethodName() + "]: ";
        logd(tag, methodName, content, thr);
    }

    private static String generateTag(StackTraceElement stack) {
        String tag = "%s(L:%d)";
        String className = stack.getClassName();
        className = className.substring(className.lastIndexOf(".") + 1);
        tag = String.format(tag, className, stack.getLineNumber());
        return tag;
    }

    public static void logCatchedException(Throwable e) {
        if (!allowLogCatchedException || null == e) {
            return;
        }
        StackTraceElement caller = Thread.currentThread().getStackTrace()[3];
        logExceptionInternal(caller, e, Integer.MAX_VALUE);
    }

    public static void logCatchedException(Throwable e, int logLineCount) {
        if (!allowLogCatchedException || null == e) {
            return;
        }
        StackTraceElement caller = Thread.currentThread().getStackTrace()[3];
        logExceptionInternal(caller, e, logLineCount);
    }

    private static void logExceptionInternal(StackTraceElement caller, Throwable e, int logLineCount) {
        String TAG = generateTag(caller);
        loge(TAG, "", e.getMessage());
        StackTraceElement[] es = e.getStackTrace();
        int finalLogLineCount = Math.min(logLineCount, es.length);
        for (int i = 0; i < finalLogLineCount; i++) {
            loge(TAG, "", es[i].toString());
        }
    }

    private static void logd(String tag, String methodName, String message) {
        Log.d(tag, methodName + message);
    }

    private static void logd(String tag, String methodName, String message, Throwable throwable) {
        Log.d(tag, methodName + message, throwable);
    }

    private static void loge(String tag, String methodName, String message) {
        Log.e(tag, methodName + message);
    }

    private static void loge(String tag, String methodName, String message, Throwable throwable) {
        Log.e(tag, methodName + message, throwable);
    }
}
